
#!coding:utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
"""
    @author jay.han
"""
import uuid
import netaddr
from cvirt.common import exception,utils

from cvirt.cnode.vm import power_state

from cvirt.common import constant
from cvirt.cnode.vm import vm_utils
from cvirt.common.test import BaseTest
from cvirt.cnode.test import fakeLibvirt,fakeUtils
from cvirt.cnode.vm import libvirtDriver,api
from cvirt.manager.models import Cluster,Storage,Instance,Server, Datacenter, VDisk, Network, Interface, FixedIp, Template

libvirtDriver.libvirt = fakeLibvirt


class TestVMapi(BaseTest):

    def setUp(self):
        super(TestVMapi, self).setUp()
        self.service = api.API
        self.service.driver = libvirtDriver.Driver()
        self.service.driver._conn = fakeLibvirt.Connection("test",False)
        api.vm_utils = fakeUtils

        self.datacenter = Datacenter.objects.create(name='datacenter1')
        self.cluster = Cluster.objects.create(name='cluster1',datacenter=self.datacenter)
        self.host = Server.objects.create(ip="172.16.10.25",host_name='node1',password='s',port=22,arch="x86_64",
                                          os="ubuntu",hypervisor='kvm',memshare=False,cpu_type='amd',qemu_version="1.0",
                                          cluster=self.cluster,status = 2)

        self.instance = Instance.objects.create(name='vm1',uuid=uuid.uuid4(),host=self.host,status='pending',
                                                power_status=1,graphics_type='vnc')
        self.storage = Storage.objects.create(name='storage1',protocol='local',mount_point='/root/cvirt_vms',host='172.16.10.25',
                                              cluster = self.cluster,totalsize=1024,type='data')

        self.isostorage = Storage.objects.create(name='iso1',protocol='local',mount_point='/root/',host='172.16.10.25',
                                              cluster = self.cluster,totalsize=1024,type='iso')

        self.network = Network.objects.create(name='host-bridge',cidr="10.0.0.0/24",rundhcp=False,networktype=2,cluster=self.cluster)
        self.network2 = Network.objects.create(name='default',cidr="10.0.0.0/24",rundhcp=False,networktype=0,cluster=self.cluster)

        self.mac  = utils.generate_mac()
        self.interface = Interface.objects.create(name='eth0',mac=self.mac,model="e1000",instance = self.instance,network=self.network)
        self.interface2 = Interface.objects.create(name='eth1',mac=self.mac,model="e1000",instance = self.instance,network=self.network2)

        self.image = Template.objects.create(name='ubuntu.qcow2',format='qcow2',size=10000,status='building',os_type="Windowsxp",
                                          storage=self.isostorage)

        self.vdisk1 = VDisk.objects.create(name='disk1',format='qcow2',device_type='disk',mountpoint='vda',
                                           size=10,max_size=10,storage=self.storage,instance = self.instance,image=self.image)

        self.vdisk2 = VDisk.objects.create(name='disk2',format='qcow2',device_type='disk',mountpoint='vdb',
                                   size=10,max_size=10,storage=self.storage,instance = self.instance)

    def test_create_vm_with_wrong_storage(self):
        self.storage.update(dict(protocol='nfs'))
        self.assertRaises(exception.Error,
                          self.service.create,self.instance)

    def test_create_vm_with_disk_params(self):
        self.vdisk1.update(dict(bus='virtio',cache="writeback",iomode="threads",readonly=True))
        inst = self.service.create(self.instance)
        self.assertEqual(inst.power_status,power_state.SHUTOFF)
        self.assertTrue('<driver name="qemu" type="qcow2" cache="writeback" io="threads"/>' in inst.xml)
        self.assertTrue('<readonly/>' in inst.xml)


    def test_create_vm_with_dhcp(self):
        self.network.update(dict(rundhcp=True))
        fixip = FixedIp.objects.create(address="10.0.0.1",allocated=True,host="172.16.10.25",network=self.network)
        inst = self.service.create(self.instance)
        self.assertEqual(inst.power_status,power_state.SHUTOFF)
        self.assertTrue('<parameter name="DHCPSERVER" value="%s"/>' % fixip.address in inst.xml)

    def test_create_vm_with_nat_dhcp(self):
        self.network.update(dict(rundhcp=True,cidr="10.0.1.0/24",networktype=1))
        inst = self.service.create(self.instance)
        dhcpip = str(netaddr.IPNetwork(self.network.cidr)[1])
        self.assertTrue('<parameter name="DHCPSERVER" value="%s"/>' % dhcpip in inst.xml)

    def test_create_vm_no_dhcp(self):
        inst = self.service.create(self.instance)
        self.assertEqual(inst.power_status,power_state.SHUTOFF)
        import re
        xml = re.sub(r"\n\s*",'',inst.xml)
        expectxml = ('<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">'
                                  '<uuid>%(uuid)s</uuid>'
                                  '<name>%(name)s</name>'
                                  '<memory>1048576</memory>'
                                  '<vcpu>1</vcpu>'
                                  '<sysinfo type="smbios">'
                                      '<bios>'
                                          '<entry name="vendor">morningcloud</entry>'
                                          '<entry name="version">1.0</entry>'
                                      '</bios>'
                                      '<system>'
                                          '<entry name="manufacturer">Tcloud</entry>'
                                          '<entry name="product">2.2</entry>'
                                          '<entry name="version">2.2</entry>'
                                          '<entry name="serial">2.2</entry>'
                                          '<entry name="uuid">%(uuid)s</entry>'
                                      '</system>'
                                  '</sysinfo>'
                                  '<os>'
                                      '<type>hvm</type>'
                                      '<boot dev="hd"/>'
                                      '<smbios mode="sysinfo"/>'
                                  '</os>'
                                  '<clock offset="localtime"/>'
                                  '<devices>'
                                      '<disk type="file" device="disk">'
                                          '<driver name="qemu" type="qcow2"/>'
                                          '<source file="%(disk_path1)s"/>'
                                          '<target bus="ide" dev="vda"/>'
                                      '</disk>'
                                          '<disk type="file" device="disk">'
                                          '<driver name="qemu" type="qcow2"/>'
                                          '<source file="%(disk_path2)s"/>'
                                          '<target bus="ide" dev="vdb"/>'
                                      '</disk>'
                                      '<input type="tablet" bus="usb"/>'
                                      '<input type="mouse" bus="ps2"/>'
                                      '<interface type="network">'
                                          '<mac address="%(mac)s"/>'
                                          '<model type="e1000"/>'
                                          '<source network="host-bridge"/>'
                                          '<filterref filter="nwfilter-%(id)s"/>'
                                      '</interface>'
                                      '<graphics type="vnc" autoport="no" listen="0.0.0.0" port="%(port)s"/>'
                                      '<sound model="ac97"/>'
                                  '</devices>'
                                  '</domain>' % dict(uuid=self.instance.uuid, disk_path1=self.vdisk1.disk_path,port=self.instance.graphics_port,
                                                     disk_path2=self.vdisk2.disk_path,
                                                     name=self.instance.name,id="%s-%s" % (self.instance.name,self.interface.name),
                                                    mac=self.mac))


        self.assertEqual(xml,expectxml)

    ## create a shutoff instance
    def testVM(self):

        inst = self.service.create(self.instance)

        self.assertEqual(inst.power_status,power_state.SHUTOFF)

        def testStartVM(start_inst):
            inst_ref = self.service.start(start_inst.id)
            self.assertEqual(inst_ref,True)

        testStartVM(inst)


        def testPauseVM(pause_vm):
            pause_inst = self.service.pause(pause_vm.id)
            self.assertEqual(pause_inst.power_status,power_state.PAUSED)


        testPauseVM(inst)


        def testResumeVM(resume_vm):
            resume_inst = self.service.unpause(resume_vm.id)
            self.assertEqual(resume_inst.power_status,power_state.RUNNING)

        testResumeVM(inst)

        def testShutDownVM(shutdown_inst):
            inst_ref = self.service.shutdown(shutdown_inst.id)
            self.assertEqual(inst_ref,True)

        testShutDownVM(inst)


        self.vdisk2.update(dict(size=20))
        self.vdisk3 = VDisk.objects.create(name='disk3',format='qcow2',device_type='disk',mountpoint='vda',
                                           size=10,max_size=10,storage=self.storage,instance = self.instance)
        def testUpdateVM(update_inst):
            instance = self.service.update(self.instance)
            self.assertEqual(instance,self.instance)

        testUpdateVM(inst)

        def testDestroy(de_vm):
            self.assertEqual(self.service.destroy(self.instance),True)

        testDestroy(inst)

    # def testListInstance(self):
    #
    #     domain = self.service.driver._lookup_by_name(self.instance['name'])
    #
    #     return domain.XMLDesc(0)

    # def testSnapshot(self):
    #     self.instance['need_launch'] = True
    #     inst = self.service.create(self.instance,self.network,self.image,self.disk)
    #
    #     snap = self.service.snapshot(inst.id,"test-snapshot","snap-description")
    #
    #     self.assertEqual(snap.status,'ok')
    #
    #     def testSnapshot_delete(inst_id,snap_id):
    #         snap = self.service.snapshot_restore(inst_id,snap_id)


    def testRegister(self):
        def get_cpu_type():
            return "amd"
        self.service.get_cpu_type = get_cpu_type
        self.service.register_host()